package org.example.encrypt.utils;

import java.math.BigDecimal;

/**
 * 数值类型加解密工具类
 *
 * @Author WeiBing
 * @Create 2024/8/14 10:03
 */
public class NumberCryptUtil {

    /*
    密钥（示例密钥，实际使用中应选择更复杂的密钥）
    但是有一个考虑的，使用XOR加解密，虽然不会更改数据类型，但是数值的长度会变化，得保证加密后得到的值精确度在数据库容纳范围内
     */
    private static final int KEY = 999;

    /**
     * 加密函数
     * 只对整数部分进行异或运算，小数部分原来是什么样，加密后拼上去还是什么样
     */
    public static BigDecimal encrypt(BigDecimal decimalValue) {
        if (null == decimalValue) {
            return null;
        }
        // 去除无效的0，直接把小数点右边不影响取值的0全去掉
        decimalValue = decimalValue.stripTrailingZeros();

        // 把这个数的整数部分和小数部分分割开
        String strDecimalValue = decimalValue.toPlainString();
        String[] split = strDecimalValue.split("\\.");

        // 肯定有整数部分
        String integerPart = String.valueOf(Long.parseLong(split[0]) ^ KEY);

        String fractionPart = "";
        if (split.length == 2) {
            fractionPart = "." + split[1];
        }

        return new BigDecimal(integerPart + fractionPart);
    }

    /**
     * 解密函数
     */
    public static BigDecimal decrypt(BigDecimal encryptedValue) {
        if (null == encryptedValue) {
            return null;
        }

        // 移除加密值右边无效的0，这一步是由于mysql存储decimal类型字段时，会根据你设置的小数部分长度给你补0，必须得把补的这些0去掉，不然解密出来是错的
        encryptedValue = encryptedValue.stripTrailingZeros();

        String strEncryptedValue = encryptedValue.toPlainString();
        String[] split = strEncryptedValue.split("\\.");

        String integerPart = String.valueOf(Long.parseLong(split[0]) ^ KEY);
        String fractionPart = "";
        if (split.length == 2) {
            fractionPart = "." + split[1];
        }

        return new BigDecimal(integerPart + fractionPart);
    }

    public static void main(String[] args) {
        // 示例原始数值
        BigDecimal originalValue = new BigDecimal("10003.56");
        BigDecimal originalValue1 = new BigDecimal("10003.560");
        BigDecimal originalValue2 = new BigDecimal("10003.006");
        BigDecimal originalValue3 = new BigDecimal("1E+5");

        // 加密
        BigDecimal encryptedValue = encrypt(originalValue);
        System.out.println("加密后的值: " + encryptedValue);
        BigDecimal encryptedValue1 = encrypt(originalValue1);
        System.out.println("加密后的值: " + encryptedValue1);
        BigDecimal encryptedValue2 = encrypt(originalValue2);
        System.out.println("加密后的值: " + encryptedValue2);
        BigDecimal encryptedValue3 = encrypt(originalValue3);
        System.out.println("加密后的值: " + encryptedValue3);

        // 解密
        BigDecimal decryptedValue = decrypt(encryptedValue);
        System.out.println("解密后的值: " + decryptedValue);
        BigDecimal decryptedValue1 = decrypt(encryptedValue1);
        System.out.println("解密后的值: " + decryptedValue1);
        BigDecimal decryptedValue2 = decrypt(encryptedValue2);
        System.out.println("解密后的值: " + decryptedValue2);
        BigDecimal decryptedValue3 = decrypt(encryptedValue3);
        System.out.println("解密后的值: " + decryptedValue3);

        /*String s = "20";
        BigDecimal bigDecimal = new BigDecimal(s);
        System.out.println(bigDecimal.remainder(BigDecimal.ONE));
        System.out.println(bigDecimal.remainder(BigDecimal.ONE).movePointRight(bigDecimal.scale()));*/

    }

}
